package M

import (
	"embed"
	"io/fs"
	"log"
	"net/http"
	"strings"
)

/**
路由设置
1、所有访问方式
2、运行的函数
3、可输入多个 要绑定的域名
**/
func (s *TServer) ANY(url string, f func(*S), domain ...string) {
	router := Router{
		Method: "",
		Uri:    url,
		Func:   f,
	}
	if domain != nil {
		router.Domain = domain
	}
	s.Router = append(s.Router, router)
}
func (s *TServer) GET(url string, f func(*S), domain ...string) {
	router := Router{
		Method: "GET",
		Uri:    url,
		Func:   f,
	}
	if domain != nil {
		router.Domain = domain
	}
	s.Router = append(s.Router, router)
}
func (s *TServer) POST(url string, f func(*S), domain ...string) {
	router := Router{
		Method: "POST",
		Uri:    url,
		Func:   f,
	}
	if domain != nil {
		router.Domain = domain
	}
	s.Router = append(s.Router, router)
}
func (s *TServer) WS(url string, f func(*S), domain ...string) {
	router := Router{
		Method: "WS",
		Uri:    url,
		Func:   f,
	}
	if domain != nil {
		router.Domain = domain
	}
	s.Router = append(s.Router, router)
}

//设置静态目录
func (s *TServer) Public(urlpath, dirpath string, domain ...string) {
	s.public[urlpath] = dirpath
}
func (s *TServer) Embed(file embed.FS) {
	s.embed = true
	s.efile = file
}

//设置静态文件
func (s *TServer) Static(urlpath, filepath string, domain ...string) {
	router := Router{
		Method: "FILE",
		Uri:    urlpath,
		Path:   filepath,
	}
	if domain != nil {
		router.Domain = domain
	}
	s.Router = append(s.Router, router)
}

//开启Session
func (s *TServer) SessionStart() {
	s.SessionConfig = SessionConfig{Start: true}
}

//运行web服务器
func (s *TServer) Run(addr ...string) {
	//静态目录设置
	if len(s.public) > 0 {
		for k, v := range s.public {
			if s.embed {
				fsys, err := fs.Sub(s.efile, v)
				if err == nil {
					http.Handle(k, http.StripPrefix(k, http.FileServer(http.FS(fsys))))
				} else {
					http.Handle(k, http.StripPrefix(k, http.FileServer(http.Dir(v))))
				}
			} else {
				http.Handle(k, http.StripPrefix(k, http.FileServer(http.Dir(v))))
			}
		}
	}
	http.HandleFunc("/", s.handle)
	if len(addr) > 0 && addr[0] != "" {
		strs := strings.Split(addr[0], ":")
		if len(strs) > 0 && strs[0] != "" {
			s.Addr = ":" + strs[0]
		}
		if len(strs) > 1 && strs[1] != "" {
			s.Addr = addr[0]
		}
	} else if s.Addr == "" {
		s.Addr = ":80"
	}
	log.Println("服务器启动端口", s.Addr)
	err := http.ListenAndServe(s.Addr, nil)
	if err != nil {
		log.Println("服务器启动失败")
	}
}

//路由处理
func (s *TServer) handle(w http.ResponseWriter, r *http.Request) {
	c := &S{}
	c.Req = r
	c.Res = w
	c.Method = r.Method
	c.Path = r.URL.Path
	c.Host = c.GetHost()
	//Host
	c.handleGet()
	c.handlePost()
	c.handSession(s.SessionConfig)
	//循环路由解析
	ifmatch := false
	for _, v := range s.Router {
		//匹配域名
		if v.Domain != nil {
			if c.matchdomains(v.Domain) == false {
				continue
			}
		}
		//匹配网址
		if !c.matchuri(v.Uri) {
			continue
		}
		ifmatch = true
		//判断websocket
		if v.Method == "WS" && v.Uri == c.Path {
			wsHandle(c, v.Func)
			break
		}
		//判断是否是静态文件
		if v.Method == "FILE" {
			c.File(v.Path)
			break
		}
		//匹配模式
		if strings.ToLower(v.Method) != strings.ToLower(c.Method) && v.Method != "" {
			ifmatch = false
			continue
		}
		v.Func(c)
		break
	}
	if ifmatch == false {
		c.Print("404")
	}
}
